using System;
using System.Net;
using System.Security;
using System.ServiceModel;

namespace FreshMeat.ErrorHandlingBlock.Wcf
{
   /// <summary>
   /// Detects and remaps permanent errors encountered by clients using WCF (Windows Communication Foundation).
   /// </summary>
   public class WcfPermanentErrorDetector : ErrorDetector
   {
      /// <summary>
      /// Checks the error and either returns it unchanged or returns a substitute error.
      /// </summary>
      protected override Exception Check(Exception error)
      {
         if (error is EndpointNotFoundException)
            return new EndpointNotFoundException("Unable to connect.");

         // Silverlight always checks for the cross-domain policy file first and if it doesn't
         // find one, then it throws this horrendously wordy top-level message with two nested 
         // security exceptions that say almost nothing.  So this becomes our "ping" -- if we
         // get this error then it most likely means we can't communicate at all.  (It's possible
         // a site really doesn't have a policy file but that should only happen when the site is
         // first being set up; by the time it goes live, this won't be about the policy file).
         // 9/1/2012 - When this code was first written, the 2nd-level inner exception was another
         //            SecurityException but that's no longer the case, most likely as a result
         //            of changes in Silverlight 5.
         if (error is CommunicationException
             && error.InnerException is SecurityException)
            //&& error.InnerException.InnerException is SecurityException)
            return new CommunicationException("Unable to connect.");

         // WCF threw this nested pattern when the web server was shut down in mid-request.
         // Not certain how much of applies to other "lost connection" errors but seems reasonable 
         // the first two levels are enough.
         if (error is CommunicationException
            && error.InnerException is WebException)
            //&& error.InnerException.InnerException is IOException
            //&& error.InnerException.InnerException.InnerException is SocketException)
            return new CommunicationException("Unable to connect.");

         return null;
      }
   }
}